package com.honghe.service.impl;

import com.honghe.constant.MessageConstant;
import com.honghe.context.BaseContext;
import com.honghe.dto.PatientDTO;
import com.honghe.dto.PatientLoginDTO;
import com.honghe.dto.VisitDTO;
import com.honghe.entity.Department;
import com.honghe.entity.Doctor;
import com.honghe.entity.DoctorPatient;
import com.honghe.entity.Patient;
import com.honghe.exception.BaseException;
import com.honghe.exception.LoginFailedException;
import com.honghe.exception.VisitException;
import com.honghe.mapper.DepartmentMapper;
import com.honghe.mapper.DocPatMapper;
import com.honghe.mapper.DoctorMapper;
import com.honghe.mapper.PatientMapper;
import com.honghe.service.PatientService;
import com.honghe.vo.DoctorVO;
import com.honghe.vo.PatOrderVO;
import com.honghe.vo.PatVisitVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
public class PatientServiceImpl implements PatientService {
    @Autowired
    private PatientMapper patientMapper;
    @Autowired
    private DocPatMapper docPatMapper;
    @Autowired
    private DoctorMapper doctorMapper;
    @Autowired
    private DepartmentMapper departmentMapper;
    public static final Integer MAX_PAT_NUM_EVERYHOURS=4;

    @Override
    public void addPatient(PatientDTO patientDTO) {
        if (!patientDTO.getPhone().matches("1[3-9]\\d{9}")) {
            throw new BaseException("手机号不合法");
        }
        Patient patient = new Patient();
        BeanUtils.copyProperties(patientDTO, patient);
        String password = patientDTO.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        patient.setPassword(password);
        patient.setCreateTime(LocalDateTime.now());
        patientMapper.addPatient(patient);
    }

    @Override
    public Patient login(PatientLoginDTO patientLoginDTO) {
        Patient patient = patientMapper.getByPhone(patientLoginDTO.getPhone());
        if (patient == null) {
            throw new LoginFailedException(MessageConstant.USER_NOT_EXIST);
        }
        String password = patientLoginDTO.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!password.equals(patient.getPassword())) {
            throw new LoginFailedException(MessageConstant.PASSWORD_ERROR);
        }
        return patient;
    }

    @Override
    public void update(PatientDTO patientDTO) {
        String password = patientDTO.getPassword();
        password=DigestUtils.md5DigestAsHex(password.getBytes());
        Patient patient=new Patient();
        BeanUtils.copyProperties(patientDTO,patient);
        patient.setPassword(password);
        patient.setId(BaseContext.getCurrentId());
        patientMapper.update(patient);
    }

    @Override
    //完美体现了十行代码实现功能，多出的二十行代码防小人
    public PatOrderVO visit(VisitDTO visitDTO) {
        String time = visitDTO.getVisitTime();
        //校验时间是否正确环节
        if (
                !time.matches("2\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (0[8-9]|1[0-9]):(00|30):00")
        ){
            throw new VisitException(MessageConstant.TIME_ERROR);
        }
        //解析时间
        DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime localDateTime=LocalDateTime.parse(time,formatter);
        //复用信息获取
        LocalDate nowDate = LocalDate.now();
        Long docId = visitDTO.getDoctorId();
        Long patId = BaseContext.getCurrentId();
        if (!Objects.equals(patId, visitDTO.getPatId())){
            throw new VisitException(MessageConstant.VERIFY_ERROR);
        }
        LocalTime localTime = localDateTime.toLocalTime();
        LocalDate localDate = localDateTime.toLocalDate();
        int hour = localTime.getHour();
        Long orderId = System.currentTimeMillis();
        //判断该时间是否在今天之前或在今天的七天之后
        if (localDate.isBefore(nowDate)|| localDate.isAfter(nowDate.plusDays(7))){
            throw new VisitException(MessageConstant.VISIT_TIME_ERROR);
        }
        //不能在12-13之间进行挂号
        if (
                localTime.isAfter(LocalTime.of(12, 0,0))&& localTime.isBefore(LocalTime.of(13, 0,0))
        ) {
            throw new VisitException(MessageConstant.VISIT_TIME_ERROR);
        }
        Map<String,Object> map = new HashMap<>();
        map.put("doc_id",docId);
        map.put("begin",LocalDateTime.of(localDate,LocalTime.of(hour,0,0)));
        map.put("end",LocalDateTime.of(localDate,LocalTime.of(hour +1,0,0)));
        Integer allPatIn1Hour = docPatMapper.countByMap(map);
        //通过以上查询这个医生在这个时间段有多少人已经挂号人数
        if (allPatIn1Hour>=MAX_PAT_NUM_EVERYHOURS){
            throw new VisitException("在"+hour+"点到"+(hour+1)+"点，该医生已经挂号人数已满");
        }
        map.put("pat_id",patId);
        map.put("begin",LocalDateTime.of(localDate,LocalTime.of(8,0,0)));
        map.put("end",LocalDateTime.of(localDate,LocalTime.of(19,0,0)));
        Integer docPat = docPatMapper.countByMap(map);
        //通过以上条件的查询来判断是否已经挂号
        if(docPat>0){
            throw new VisitException(MessageConstant.HAVE_REGISTERED_ON_THIS_DAY);
        }
        Patient patient = patientMapper.getById(patId);
        Doctor doctor = doctorMapper.getById(docId);
        if(doctor == null){
            throw new VisitException(MessageConstant.DOCTOR_NOT_EXIST);
        }
        DoctorPatient doctorPatient=new DoctorPatient();
        BeanUtils.copyProperties(visitDTO,doctorPatient);
        //设置挂号信息
        doctorPatient.setPatientId(patient.getId());
        doctorPatient.setPhone(patient.getPhone());
        doctorPatient.setName(patient.getName());
        doctorPatient.setVisitTime(localDateTime);
        doctorPatient.setStatus(DoctorPatient.NO_DONE);
        doctorPatient.setOrderId(orderId);

        docPatMapper.addVisitPatient(doctorPatient);
        return new PatOrderVO(
                doctor.getName(),
                doctor.getSex(),
                doctor.getAge(),
                localDateTime,
                orderId
        );
    }

    @Override
    public List<DoctorVO> getByDeptId(Long deptId) {
        Department dept = departmentMapper.getById(deptId);
        if (dept == null){
            throw new BaseException(MessageConstant.DEPT_NOT_EXIST);
        }
        List<Doctor> doctor = doctorMapper.getByDeptId(deptId);
        List<DoctorVO> doctorVOS=new ArrayList<>();
        for (Doctor d:doctor){
            DoctorVO doctorVO=new DoctorVO();
            BeanUtils.copyProperties(d,doctorVO);
            String sex = d.getSex() == 1 ? "男" : "女";
            doctorVO.setSex(sex);
            doctorVOS.add(doctorVO);
        }
        return doctorVOS;
    }

    @Override
    public List<PatVisitVO> getAllDeptWithDoc() {
        List<PatVisitVO> patVisitVOS = new ArrayList<>();
        List<Department> all = departmentMapper.getAll();
        for (Department department:all){
            PatVisitVO patVisitVO = new PatVisitVO();
            Long deptId = department.getId();
            List<DoctorVO> doctorVOS = this.getByDeptId(deptId);//这里多加的this是方便可读，表示是在本类中调用本类的一个service方法
            patVisitVO.setId(deptId);
            patVisitVO.setName(department.getName());
            patVisitVO.setDoctors(doctorVOS);
            patVisitVOS.add(patVisitVO);
        }
        return patVisitVOS;
    }

    @Override
    public List<PatOrderVO> getMyVisit(Long patId) {
        Long patientId = BaseContext.getCurrentId();
        if (!Objects.equals(patientId, patId)){
            throw new VisitException(MessageConstant.VERIFY_ERROR);
        }
        List<PatOrderVO> patOrderVOS=docPatMapper.getDocByPatId(patId);
        return patOrderVOS;
    }

    @Override
    public void updateStatus(Long orderId) {
        Long visitId = docPatMapper.getByOrderId(orderId);
        docPatMapper.updateStatus(visitId,DoctorPatient.DOC_DID_NOT_ARRIVE);
    }
}